<?php
    class privilege_model extends Model
    {
    	const P_VIEW = 0x1;
        const P_MODIFY = 0x2;
        const P_DISPOSE = 0x4;
        const P_GIVE_VIEW = 0x8;
        const P_GIVE_MODIFY = 0x10;
        const P_GIVE_DISPOSE = 0x20;
        
        private $userModel;
        private $taskModel;

        public function __construct(){
            parent::__construct();
            $this->setTableName('privileges');
            $this->userModel = $this->load->model('user');
            $this->taskModel = $this->load->model('task');
        }
        
        /*
        	@param int user's id to set privilege
            @param int task's id to set privilege
            @param int type in class const type as mask
            @param boolean set bit on or off
            @return boolean action success
        */
        public function set($userId, $taskId, $type, $value){
            $info = $this->get($userId, $taskId, $type);
            
            list($list, $selection) = $this->_buildSelectStr();
            if (empty($list)) return false;
            
            if (empty($info)){
            	//insert
                $sql = 'insert into ' . $this->getTableName()
               		. ' (' . $selection . ') values(' 
                    . implode(', ', array_fill(0, count($list), '{0}')) . ')';
            }
            else{
            	//update
                $sql = 'update ' . $this->getTableName()
                	. ' set ';
                
                $sql .= implode(' = {0}, ', $list);
                
                $sql = substr($sql, 0, 0 - strlen(' = {0}, '));
                
                $sql .= ' limit 1';
            }
            
            return $this->db->query($sql, array($value));
        }
        
        /*
        	@param int user's id to get privilege
            @param int task's id to get privilege
            @param int type in class const type as mask
            @return boolean? bit value or action unsuccess
        */
        public function get($userId, $taskId, $type){
        	$userId = intval($userId);
            if (null != $taskId) $taskId = intval($taskId);
            $type = intval($type);
            if (empty($userId)) return null;
            
            //check user existence
           	if (!$this->userModel->exists($userId)) return null;
            //check task existence
            if (null != $taskId && !$this->taskModel->exists($taskId)) return null;
            
            //do get, using mask to fetch
            list(, $selection) = $this->_buildSelectStr($type);
            $sql = 'select ' . $selection . ' from ' . $this->getTableName()
            	. ' where user_id = {0} and task_id = {1} limit 1';
                
        	return $this->db->fetchOne($sql, array($userId, $taskId));
        }
        
        /*
        	@param int task's id to get privilege
            @return array list of user's allowed privilege list
        */
        public function getViewUserList($taskId){
        	if (null != $taskId) $taskId = intval($taskId);
            
            //check task existence
            if (null != $taskId && !$this->taskModel->exists($taskId)) return null;
            
            //do get, using mask to fetch
            
            $thisTableName = $this->getTableName();
            $userTableName = $this->userModel->getTableName();
            
            $sql = 'select ';
            $sql .= ($userTableName . '.id as id ');
            $sql .= ($userTableName . '.username as username ');
            $sql .= ($userTableName . '.mobile as mobile ');
            $sql .= ($userTableName . '.email as email ');
            $sql .= ($userTableName . '.activated as activated ');
            $sql .= (' from ' . $thisTableName . ' as tblT, ');
            $sql .= ($userTableName . ' as tblU ');
            $sql .= ' where tblU.id = tblT.user_id and ((tblT.task_id = {0}) or (tblT.task_id = NULL)) and view = 1';
            
            return $this->db->fetch($sql, array($taskId));
        }
        
        /*
        	@param int type of selection
            @return string selection filter string
        */
        private function _buildSelectStr($type){
        	$selection = array();
        	if ($type & self::P_VIEW)
            	array_push($selection, 'view');
            if ($type & self::P_MODIFY)
            	array_push($selection, 'modify');
            if ($type & self::P_DISPOSE)
            	array_push($selection, 'dispose');
            if ($type & self::P_GIVE_VIEW)
            	array_push($selection, 'give_view');
            if ($type & self::P_GIVE_MODIFY)
            	array_push($selection, 'give_modify');
            if ($type & self::P_GIVE_DISPOSE)
            	array_push($selection, 'give_dispose');
            
            if (empty($selection)) 
            	return array($selection, '*');
            else
            	return array($selection, implode(', ', $selection));
        }
        
    }